package one.stand.controller;

import com.alibaba.fastjson.JSON;
import com.jmp.autocofiguration.util.OssUtil2;
import com.jmp.base.SecurityApi;
import com.jmp.base.dto.*;
import com.jmp.feign.AccountFeign;
import com.jmp.feign.MessageFeign;
import com.jmp.feign.SmsFeign;
import com.jmp.security.DefaultAuthenticationManager;
import com.jmp.security.TokenEntityServiceImpl;
import com.jmp.security.base.*;
import com.jmp.security.client.CompanyKeyClientDetailService;
import com.jmp.security.grant.CardUserDetailValidServiceImpl;
import com.jmp.security.grant.CompanyKeyUserDetailValidServiceImpl;
import com.jmp.security.grant.PasswordUserDetailServiceImpl;
import com.jmp.security.grant.UserDetailValidServiceImpl;
import com.jmp.security.grant.crmApp.CrmAppSmsRequestDetail;
import com.jmp.security.grant.crmApp.CrmAppSmsUserDetailServiceImpl;
import com.jmp.security.grant.crmApp.CrmAppWx2UserDetailServiceImpl;
import com.jmp.security.grant.crmApp.CrmAppWxUserDetailServiceImpl;
import com.jmp.security.grant.crmPc.*;
import com.jmp.security.grant.gzhApi.GzhApiWxRequestDetail;
import com.jmp.security.grant.gzhApi.GzhApiWxUserDetailServiceImpl;
import com.jmp.security.grant.jxsApp.JxsAppPasswordRequestDetail;
import com.jmp.security.grant.jxsApp.JxsAppSmsRequestDetail;
import com.jmp.security.grant.jxsApp.JxsAppSmsUserDetailServiceImpl;
import com.jmp.security.grant.jxsApp.JxsAppWxUserDetailServiceImpl;
import com.jmp.security.grant.userApi.UserApiWxUserDetailServiceImpl;
import com.jmp.security.grant.wx.*;
import com.jmp.security.response.FailResponseHandlerImpl;
import com.jmp.security.response.SuccessResponseHandlerImpl;
import lombok.extern.slf4j.Slf4j;
import one.stand.advice.ResultEnum;
import one.stand.config.SecurityProperties;
import one.stand.entity.TokenEntity;
import one.stand.enums.LoginEnum;
import one.stand.exception.LoginException;
import one.stand.mapper.*;
import one.stand.model.*;
import one.stand.response.LoginResponse;
import one.stand.service.*;
import one.stand.service.sys.SysDictValueService;
import one.stand.service.user.TokenService;
import one.stand.service.user.UserAdminService;
import one.stand.util.AssertUtil;
import one.stand.util.Md5Util;
import one.stand.util.OneIllegalArgumentException;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Objects;

@RestController
@Slf4j
public class SecurityController implements SecurityApi {
    private UserAdminService userAdminService;
    private SysDictValueService sysDictValueService;
    private TokenService tokenService;

    private AuthenticationManager<WxCodeRequestDetail> userApiWxAuthenticationManager;

    private AuthenticationManager<WxAppRquestDetail> crmAppWxAuthenticationManager;
    private AuthenticationManager<CrmAppWx2UserDetailServiceImpl.Wx2CodeRequestDetail> crmAppWx2AuthenticationManager;
    private AuthenticationManager<CrmAppSmsRequestDetail> crmAppSmsAuthenticationManager;
    private AuthenticationManager<CrmAppPasswordRequestDetail> crmAppPasswordAuthenticationManager;

    private AuthenticationManager<WxAppRquestDetail> jxsAppWxAuthenticationManager;
    private AuthenticationManager<JxsAppSmsRequestDetail> jxsAppSmsAuthenticationManager;
    private AuthenticationManager<JxsAppPasswordRequestDetail> jxsAppPasswordAuthenticationManager;

    private AuthenticationManager<AdminCompanyRequestDetail> crmPcAdminCompanyAuthenticationManager;
    private AuthenticationManager<CrmPcSmsRequestDetail> crmPcSmsAuthenticationManager;
    private AuthenticationManager<CrmPcWxImgRequestDetail> crmPcWxImgAuthenticationManager;

    private AuthenticationManager<GzhApiWxRequestDetail> gzhApiWxAuthenticationManager;

    @Autowired
    private HomeService homeService;
    @Autowired
    private ChatService chatService;
    @Autowired
    private AdminMapperExt adminMapperExt;

    @Autowired
    public SecurityController(SmsFeign smsFeign,
                              AccountFeign accountFeign,
                              MessageFeign messageFeign,
                              SysDictValueService sysDictValueService,
                              UserAdminService userAdminService,
                              BusinessCardBaseService businessCardBaseService,

                              SecurityProperties securityProperties,
                              CompanyEquService companyEquService,
                              CompanyMapperExt companyMapperExt,
                              TokenService tokenService,
                              CompanyPlatformMapperServiceLoginExt companyPlatformMapperServiceLoginExt,
                              WxLoginService wxLoginService,
                              SecurityClientMapperExt securityClientMapperExt,
                              UserService userService) {

        this.userAdminService = userAdminService;
        this.sysDictValueService = sysDictValueService;
        this.tokenService = tokenService;

        final ResponseHandler successResponseHandler = new SuccessResponseHandlerImpl(messageFeign);
        final ResponseHandler failResponseHandler = new FailResponseHandlerImpl();
        final TokenEntityService tokenEntityService = new TokenEntityServiceImpl(tokenService);

        //名片小程序
        ClientDetailService clientDetailService = new CompanyKeyClientDetailService(accountFeign, securityClientMapperExt);
        UserDetailService<WxCodeRequestDetail> userDetailService = new UserApiWxUserDetailServiceImpl(userAdminService, wxLoginService, companyPlatformMapperServiceLoginExt, userService);
        UserDetailValidService<WxCodeRequestDetail> userDetailValidService = new UserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt);
        this.userApiWxAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                userDetailService, userDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);


        //名片Crm App
        UserDetailService<WxAppRquestDetail> crmAppuserDetailService = new CrmAppWxUserDetailServiceImpl(userAdminService, userService);
        UserDetailValidService<WxAppRquestDetail> crmAppUserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.crmAppWxAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                crmAppuserDetailService, crmAppUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<CrmAppWx2UserDetailServiceImpl.Wx2CodeRequestDetail> crmAppWxuserDetailService = new CrmAppWx2UserDetailServiceImpl(userAdminService, wxLoginService, messageFeign, userService);
        UserDetailValidService<CrmAppWx2UserDetailServiceImpl.Wx2CodeRequestDetail> crmAppWxuserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.crmAppWx2AuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                crmAppWxuserDetailService, crmAppWxuserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<CrmAppSmsRequestDetail> crmAppSmsUserDetailService = new CrmAppSmsUserDetailServiceImpl(securityProperties, smsFeign, userAdminService, userService);
        UserDetailValidService<CrmAppSmsRequestDetail> crmAppSmsUserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.crmAppSmsAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                crmAppSmsUserDetailService, crmAppSmsUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<CrmAppPasswordRequestDetail> crmAppPasswordRequestDetailUserDetailService = new PasswordUserDetailServiceImpl<>(userService);
        UserDetailValidService<CrmAppPasswordRequestDetail> crmAppPasswordRequestDetailUserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.crmAppPasswordAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                crmAppPasswordRequestDetailUserDetailService, crmAppPasswordRequestDetailUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);


        //Jxs App
        UserDetailService<WxAppRquestDetail> jxsAppuserDetailService = new JxsAppWxUserDetailServiceImpl(userAdminService, userService);
        UserDetailValidService<WxAppRquestDetail> jxsAppuserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.jxsAppWxAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                jxsAppuserDetailService, jxsAppuserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<JxsAppSmsRequestDetail> jxsAppSmsUserDetailService = new JxsAppSmsUserDetailServiceImpl(securityProperties, smsFeign, userAdminService, userService);
        UserDetailValidService<JxsAppSmsRequestDetail> jxsAppSmsUserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.jxsAppSmsAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                jxsAppSmsUserDetailService, jxsAppSmsUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<JxsAppPasswordRequestDetail> jxsAppPasswordRequestDetailUserDetailService = new PasswordUserDetailServiceImpl<>(userService);
        UserDetailValidService<JxsAppPasswordRequestDetail> jxsAppPasswordRequestDetailUserDetailValidService = new CompanyKeyUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt, companyPlatformMapperServiceLoginExt, sysDictValueService);
        this.jxsAppPasswordAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                jxsAppPasswordRequestDetailUserDetailService, jxsAppPasswordRequestDetailUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);


        //名片Crm Pc
        UserDetailService<AdminCompanyRequestDetail> crmPcAdminUserDetailService = new AdminCompanyUserDetailServiceImpl(companyMapperExt, userAdminService);
        UserDetailValidService<AdminCompanyRequestDetail> crmPcAdminUserDetailValidService = new CardUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt);
        this.crmPcAdminCompanyAuthenticationManager = new DefaultAuthenticationManager<>(null,
                crmPcAdminUserDetailService, crmPcAdminUserDetailValidService
                , tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<CrmPcSmsRequestDetail> crmPcSmsuserDetailService = new CrmPcSmsUserDetailServiceImpl(userAdminService, userService);
        UserDetailValidService<CrmPcSmsRequestDetail> crmPcSmsuserDetailValidService = new CrmPcSmsUserDetailValidServiceImpl(businessCardBaseService, companyMapperExt, securityProperties, smsFeign);
        this.crmPcSmsAuthenticationManager = new DefaultAuthenticationManager<>(null,
                crmPcSmsuserDetailService, crmPcSmsuserDetailValidService
                , tokenEntityService, successResponseHandler, failResponseHandler);
        UserDetailService<CrmPcWxImgRequestDetail> crmPcuserDetailService = new WxImgUserDetailServiceImpl<>(wxLoginService, userAdminService, userService);
        UserDetailValidService<CrmPcWxImgRequestDetail> crmPcuserDetailValidService = new CardUserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt);
        this.crmPcWxImgAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                crmPcuserDetailService, crmPcuserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);


        //公众号
        UserDetailService<GzhApiWxRequestDetail> gzhApiUserDetailService = new GzhApiWxUserDetailServiceImpl(userAdminService, wxLoginService, userService);
        UserDetailValidService<GzhApiWxRequestDetail> gzhApiUserDetailValidService = new UserDetailValidServiceImpl<>(businessCardBaseService, companyMapperExt);
        this.gzhApiWxAuthenticationManager = new DefaultAuthenticationManager<>(clientDetailService,
                gzhApiUserDetailService, gzhApiUserDetailValidService,
                tokenEntityService, successResponseHandler, failResponseHandler);
    }

    @Override
    public ResultModel<ShowroomLoginImgResponse> showroomLoginImg(@RequestBody ShowroomLoginImgRequest request) {
        try {
            String codeUrl = homeService.getShowRoomLoginCode(request.getEquCode(), request.getLoginEnum());
            String token = homeService.getShowRoomNoLogin(request.getEquCode(), request.getLoginEnum());
            ShowroomLoginImgResponse response = ShowroomLoginImgResponse.builder()
                    .codeUrl(codeUrl)
                    .token(token)
                    .build();
            return ResultModel.success(response);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
            return ResultModel.error();
        }
    }

    @Override
    public ResultModel<ShowroomLoginResponse> showroomLogin(@RequestBody ShowroomLoginRequest request) {
        try {
            LoginResponse loginResponse = homeService.showroomLogin(request.getCode(), request.getEquCode(), request.getLoginEnum());
            ShowroomLoginResponse response = ShowroomLoginResponse.builder()
                    .token(loginResponse.getToken())
                    .userName(loginResponse.getUserName())
                    .avatarUrl(loginResponse.getAvatarUrl())
                    .cardId(loginResponse.getCardId())
                    .build();
            return ResultModel.success(response);
        } catch (LoginException e) {
            log.error(e.getMessage(), e);
            return ResultModel.fail();
        }
    }

    @Override
    public ResultModel<LoginResponse> loginIpadWx(@RequestBody SecurityLoginIpadWxRequest request) {
        return homeService.pcLoginCallBack(request.getCode(), request.getEquCode(), null, LoginEnum.IPAD);
    }

    @Override
    public ResultModel<LoginResponse> loginIpadPwd(@RequestBody SecurityLoginIpadPwdRequest request) {
        return homeService.loginIpadPwd(request.getUsername(), request.getPassword(), LoginEnum.IPAD);
    }

    @Override
    public ResultModel<LoginAdminVo> loginAdmin(@RequestBody SecurityLoginAdminDto request) {
        AssertUtil.isFalse(request == null || StringUtils.isBlank(request.getLoginName()) || StringUtils.isBlank(request.getPassWord()), ResultEnum.PARAM_CHECK, "请输入管理员账号或密码~！");

        Admin model = adminMapperExt.selectByName(request.getLoginName());
        AssertUtil.nonNull(model, ResultEnum.PARAM_CHECK, "登录账号无效~！");
        AssertUtil.isTrue(model.getIsDel() == 0, ResultEnum.PARAM_CHECK, "登录账号禁用~！");
        AssertUtil.isTrue(Md5Util.md5(request.getPassWord()).equals(model.getPassWord()), ResultEnum.PARAM_CHECK, "登录密码错误~！");

        TokenEntity tokenEntity = new TokenEntity();
        tokenEntity.setId(model.getAdminId().longValue());
        tokenEntity.setLoginProgramName(LoginEnum.ADMIN.getCode());
        tokenEntity.setCId(model.getAdminId().longValue());
        tokenEntity.setTourist(model.getTourist());
        tokenService.saveAdmin(tokenEntity);

        LoginAdminVo vo = LoginAdminVo.builder()
                .token(tokenEntity.getToken())
                .userId(model.getAdminId())
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel<LoginResponse> loginAdminCompany(@RequestBody SecurityLoginAdminCompanyRequest request) {
        try {
            AdminCompanyRequestDetail requestDetail = AdminCompanyRequestDetail.builder()
                    .companyId(request.getCompanyId())
                    .build();
            ResponseDetail responseDetail = crmPcAdminCompanyAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);// 与crm api登录返回结果保持一致
            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginCrmPcWx(@RequestBody SecurityLoginCrmPcWxRequest request) {
        return homeService.pcLoginCallBack(request.getCode(), null, request.getState(), LoginEnum.CRM_PC);
    }

    @Override
    public ResultModel<LoginResponse> loginCrmPcPhone(@RequestBody SecurityLoginCrmPcPhoneRequest request) {
        return homeService.crmPcLoginBySms(request.getCompanyId(), request.getPhone(), request.getSmsCode());
    }

    @Override
    public ResultModel<LoginResponse> loginCrmApiPassword(@RequestBody SecurityLoginCrmApiPasswordRequest request) {
//        return homeService.loginIpadPwd(request.getUsername(), request.getPassword(), LoginEnum.CRM);
        try {
            String companyKey = request.getCompanyKey();
            if (StringUtils.isBlank(request.getCompanyKey())) {
                SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
                companyKey = sysDictValue.getValue();
            }
            CrmAppPasswordRequestDetail requestDetail = CrmAppPasswordRequestDetail.builder()
                    .companyKey(companyKey)
                    .build();
            requestDetail.setUsername(request.getUsername());
            requestDetail.setPassword(request.getPassword());
            ResponseDetail responseDetail = crmAppPasswordAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginCrmApiSms(@RequestBody SecurityLoginCrmApiPasswordRequest request) {
        try {
            String companyKey = request.getCompanyKey();
            if (StringUtils.isBlank(request.getCompanyKey())) {
                SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
                companyKey = sysDictValue.getValue();
            }
            CrmAppSmsRequestDetail requestDetail = CrmAppSmsRequestDetail.builder()
                    .companyKey(companyKey)
                    .phone(request.getUsername())
                    .smsCode(request.getPassword())
                    .pushCid(request.getPushCid())
                    .clientEnum("quanjing".equals(request.getCompanyKey()) ? ClientEnum.CRM_API_QUANJING : ClientEnum.CRM_API_HUAYUAN)
                    .build();
            ResponseDetail responseDetail = crmAppSmsAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginCrmApiWx(@RequestBody SecurityLoginCrmApiWxRequest request) {

        try {
            WxAppRquestDetail.AppOauth appOauth = getWxInfo(request.getAppOauth());

            WxAppRquestDetail wxRequestDetail = WxAppRquestDetail.builder()
                    .loginEnum(LoginEnum.CRM)
                    .companyKey(request.getCompanyKey())
                    .appOauth(appOauth)
                    .pushCid(request.getClientId())
                    .clientEnum("quanjing".equals(request.getCompanyKey()) ? ClientEnum.CRM_API_QUANJING : ClientEnum.CRM_API_HUAYUAN)
                    .build();
            ResponseDetail responseDetail = crmAppWxAuthenticationManager.authentication(wxRequestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginCrmApiWx2(@RequestBody SecurityLoginCrmApiWx2Request request) {
        try {
            CrmAppWx2UserDetailServiceImpl.Wx2CodeRequestDetail wxRequestDetail = CrmAppWx2UserDetailServiceImpl.Wx2CodeRequestDetail.builder().build();
            wxRequestDetail.setLoginEnum(LoginEnum.CRM);
            wxRequestDetail.setCompanyKey(request.getCompanyKey());
            wxRequestDetail.setCode(request.getCode());
            wxRequestDetail.setPushCid(request.getClientId());
            wxRequestDetail.setClientEnum(Objects.nonNull(request.getClientEnum()) ? request.getClientEnum() : ClientEnum.CRM_APP);
            ResponseDetail responseDetail = crmAppWx2AuthenticationManager.authentication(wxRequestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginCrmAppSms(@RequestBody SecurityLoginCrmApiPasswordRequest request) {
        try {
            String companyKey = request.getCompanyKey();
            if (StringUtils.isBlank(request.getCompanyKey())) {
                SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
                companyKey = sysDictValue.getValue();
            }
            CrmAppSmsRequestDetail requestDetail = CrmAppSmsRequestDetail.builder()
                    .companyKey(companyKey)
                    .phone(request.getUsername())
                    .smsCode(request.getPassword())
                    .pushCid(request.getPushCid())
                    .clientEnum(Objects.nonNull(request.getClientEnum()) ? request.getClientEnum() : ClientEnum.CRM_APP)
                    .build();
            ResponseDetail responseDetail = crmAppSmsAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginUserApiWx(@RequestBody SecurityLoginUserApiWxRequest request) {

        try {

            WxCodeRequestDetail wxRequestDetail = WxCodeRequestDetail.builder()
                    .loginEnum(LoginEnum.USER)
                    .companyKey(request.getCompanyKey())
                    .code(request.getCode())
                    .encrypteData(request.getEncrypteData())
                    .iv(request.getIv())
                    .build();
            ResponseDetail responseDetail = userApiWxAuthenticationManager.authentication(wxRequestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);
            boolean isAuth = !userAdminService.isVisit(responseDetail.getUserDetail().getUserModel().getAvatarUrl());
            loginResponse.setAuth(isAuth);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<SecurityLoginGzhApiResponse> loginGzhApiWx(@RequestBody SecurityLoginGzhApiRequest request) {
        try {
            SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
            String companyKey = sysDictValue.getValue();
            GzhApiWxRequestDetail requestDetail = GzhApiWxRequestDetail.builder()
                    .code(request.getCode())
                    .loginEnum(request.getLoginEnum())
                    .companyKey(companyKey)
                    .build();
            ResponseDetail responseDetail = gzhApiWxAuthenticationManager.authentication(requestDetail);
            if (!responseDetail.isSuccess()) {
                throw responseDetail.getException();
            }

            User userModel = responseDetail.getUserDetail().getUserModel();
            Integer cardId = Objects.nonNull(responseDetail.getUserDetail().getCardModel()) ? responseDetail.getUserDetail().getCardModel().getCardId() : null;

            SecurityLoginGzhApiResponse response = SecurityLoginGzhApiResponse.builder()
                    .token(responseDetail.getToken())
                    .userId(userModel.getUserId())
                    .userName(userModel.getNickeName())
                    .avatarUrl(userModel.getAvatarUrl())
                    .phone(userModel.getPhone())
                    .cardId(cardId)
                    .build();
            return ResultModel.success(response);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginJxsApiPassword(@RequestBody SecurityLoginJxsApiPasswordRequest request) {
        try {
            String companyKey = request.getCompanyKey();
            if (StringUtils.isBlank(request.getCompanyKey())) {
                SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
                companyKey = sysDictValue.getValue();
            }
            JxsAppPasswordRequestDetail requestDetail = JxsAppPasswordRequestDetail.builder()
                    .companyKey(companyKey)
                    .build();
            requestDetail.setUsername(request.getUsername());
            requestDetail.setPassword(request.getPassword());
            ResponseDetail responseDetail = jxsAppPasswordAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginJxsApiSms(@RequestBody SecurityLoginJxsApiPasswordRequest request) {
        try {
            String companyKey = request.getCompanyKey();
            if (StringUtils.isBlank(request.getCompanyKey())) {
                SysDictValue sysDictValue = sysDictValueService.get(SysDictValueService.Type.default_company_key, SysDictValueService.TypeName.default_company_key);
                companyKey = sysDictValue.getValue();
            }
            JxsAppSmsRequestDetail requestDetail = JxsAppSmsRequestDetail.builder()
                    .companyKey(companyKey)
                    .phone(request.getUsername())
                    .smsCode(request.getPassword())
                    .pushCid(request.getPushCid())
                    .clientEnum(ClientEnum.CRM_JXS)
                    .build();
            ResponseDetail responseDetail = jxsAppSmsAuthenticationManager.authentication(requestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    @Override
    public ResultModel<LoginResponse> loginJxsApiWx(@RequestBody SecurityLoginJxsApiWxRequest request) {
        try {
            WxAppRquestDetail.AppOauth appOauth = getWxInfo(request.getAppOauth());

            WxAppRquestDetail wxRequestDetail = WxAppRquestDetail.builder()
                    .loginEnum(LoginEnum.JXS_APP)
                    .companyKey(request.getCompanyKey())
                    .appOauth(appOauth)
                    .pushCid(request.getClientId())
                    .clientEnum(ClientEnum.CRM_JXS)
                    .build();
            ResponseDetail responseDetail = jxsAppWxAuthenticationManager.authentication(wxRequestDetail);

            LoginResponse loginResponse = loginResponse(responseDetail);

            return ResultModel.success(loginResponse);
        } catch (Exception e) {
            return exceptionHandler(e);
        }
    }

    private LoginResponse loginResponse(ResponseDetail responseDetail) throws Exception {

        if (!responseDetail.isSuccess()) {
            throw responseDetail.getException();
        }

        User userModel = responseDetail.getUserDetail().getUserModel();
        BusinessCard cardModel = responseDetail.getUserDetail().getCardModel();

        LoginResponse loginResponse = new LoginResponse();
        loginResponse.setUserId(Long.valueOf(userModel.getUserId()));
        loginResponse.setToken(responseDetail.getToken());
        loginResponse.setAvatarUrl(userModel.getAvatarUrl());
        loginResponse.setUserName(userModel.getNickeName());
        loginResponse.setRoleId(userModel.getRoleId());
        loginResponse.setOssUrl(OssUtil2.getWebsiteUrl());
        loginResponse.setPhone(userModel.getPhone());
        if (null != cardModel) {
            loginResponse.setCardId(cardModel.getCardId());
            Company companyModel = responseDetail.getUserDetail().getCompany();
            loginResponse.setCompanyName(companyModel.getCompanyName());
            loginResponse.setQjSupplyState(companyModel.getQjSupplyState());
            loginResponse.setQjAgentState(companyModel.getQjAgentState());
            loginResponse.setIsAgent(companyModel.getIsAgent());
        } else {
            loginResponse.setCardId(0);
        }

        log.info("response: {}", JSON.toJSONString(loginResponse));

        chatService.get(userModel.getUserId());

        return loginResponse;
    }

    private <T> ResultModel<T> exceptionHandler(Exception e) {
        if (e instanceof OneLoginWxErrorException) {
            log.error(e.getMessage(), e);
            return ResultModel.fail(ResultEnum.FAIL_LOGIN_BadPadding);
//        } else if (e instanceof DuplicateKeyException) {
//            log.error(e.getMessage(), e);
//            return ResultModel.success();
        } else if (e instanceof OneIllegalArgumentException) {// 验证失败返回对应错误
            log.error(e.getMessage(), e);
            return ResultModel.fail(((OneIllegalArgumentException) e).getCode(), e.getMessage());
        } else {
            log.error(e.getMessage(), e);
            return ResultModel.fail(ResultEnum.FAIL_LOGIN_ERROR);
        }
    }

    private WxAppRquestDetail.AppOauth getWxInfo(Map<String, Object> appOauth) {
        return WxAppRquestDetail.AppOauth.builder()
                .unionid(MapUtils.getString(appOauth, "unionid"))
                .sessionKey(MapUtils.getString(appOauth, "access_token"))
                .openId(MapUtils.getString(appOauth, "openId"))
                .userInfo(JSON.toJSONString(MapUtils.getMap(appOauth, "userInfo")))
                .build();
    }
}
